// sdk_demo
var PJO = (function () {
  // 模块信息
  var modelinfo = {
    debug: false,
    version: '1.0.0',
    develope: '2024-01-25',
    release: '2023-11-15'
  }
  Object.defineProperty(modelinfo, 'version', {
    value: modelinfo.version,
    writable: false
  })
  Object.defineProperty(modelinfo, 'develope', {
    value: modelinfo.develope,
    writable: false
  })
  Object.defineProperty(modelinfo, 'release', {
    value: modelinfo.release,
    writable: false
  })

  // 发送消息给原生应用并返回 Promise
  function postMessage(model) {
    return new Promise(function (resolve, reject) {
      model.sdkInfo = window.PJO.modelinfo
      var fail = model.module + model.method + '_Fail'
      var beforfail = 'before' + fail
      var success = model.module + model.method + '_Success'
      var beforesuccess = 'before' + success

      // 调试信息
      consolelog(
        '[webview jsbridge] called app:' +
          'module:' +
          model.module +
          ',method:' +
          model.method +
          ',model:' +
          JSON.stringify(model) +
          ',logtime:' +
          new Date()
      )

      if (!model.method) {
        // 如果方法未定义，处理错误并拒绝 Promise
        var msg = { message: '[webview jsbridge] method is undefined', logtime: new Date() }
        model.fail(msg)
        reject(msg)
        return
      }

      // 设置成功回调函数
      window[success] = model.success
      window[beforesuccess] = function (res) {
        // 解析json
        var json = parseResponse(res)
        // 输出解析结果
        consolelog('[webview jsbridge] app return fail:' + JSON.stringify(json))
        // 将解析结果传给回调函数
        window[success] ? window[success](json) : null
        resolve(json)
        // 销毁回调函数
        destorycallback(success, beforesuccess, fail, beforfail)
      }
      model.success = beforesuccess

      // 设置失败回调函数
      window[fail] = model.fail
      window[beforfail] = function (res) {
        // 解析json
        var json = parseResponse(res)
        // 输出解析结果
        consolelog('[webview jsbridge] app return fail:' + JSON.stringify(json))
        // 将解析结果传给回调函数
        window[fail] ? window[fail](json) : null
        reject(json)
        // 销毁回调函数
        destorycallback(success, beforesuccess, fail, beforfail)
      }
      model.fail = beforfail

      try {
        if (typeof webkit === 'undefined') {
          // 非webkit内核浏览器
          PiccWebBridgeInterface[model.module](JSON.stringify(model))
        } else {
          // webkit内核浏览器
          window.webkit.messageHandlers[model.module].postMessage(JSON.stringify(model))
        }
      } catch (error) {
        // 处理调用错误
        var msg = {
          message: '[webview jsbridge] your app does not implement method:' + model.method,
          logtime: new Date()
        }
        console.warn(msg)
        reject(msg)
        if (window[beforfail]) window[beforfail](msg)
      }
    })
  }

  // 控制台日志，仅在调试模式下记录
  function consolelog(log) {
    if (window.PJO.modelinfo.debug) console.log(log)
  }

  // 销毁回调函数
  function destorycallback() {
    var _args = Array.prototype.slice.call(arguments)
    _args.forEach((arg) => {
      window[arg] = null
      delete window[arg]
      consolelog(`[webview jsbridge] destorycallback:` + arg)
    })
  }

  // 创建模块函数
  function createModuleFunction(module, method) {
    return function (model = {}) {
      model.method = method
      model.module = module
      return postMessage(model)
    }
  }

  // 创建模块函数前的钩子函数
  function beforeCreateModuleFunction(module, method) {
    createModuleFunction(module, method)
  }

  // 解析返回数据
  function parseResponse(res) {
    // 如果输入为空或 undefined，则返回 null
    if (!res) return null
    // 如果输入已经是对象，则直接返回
    if (typeof res !== 'string') return res
    try {
      // 尝试解码 URI 组件
      var json = decodeURIComponent(res)
      // 移除换行和空白字符
      json = json
        .replace(/\n/g, '')
        .replace(/\r/g, '')
        .replace(/\s|\xA0/g, '')
      // 尝试将字符串解析为 JSON 对象
      var jsonOK = JSON.parse(json)
      // 检查解析结果是否为对象，如果不是，返回 null
      if (typeof jsonOK === 'object' && jsonOK !== null) {
        return jsonOK
      } else {
        // 如果解析后的结果不是对象，直接返回原数据
        return res
      }
    } catch (error) {
      // 解析失败时直接返回原数据
      return res
    }
  }

  // 模块和方法的配置
  var modules = {
    user: {
      module: 'jssdkCallUser',
      methods: {
        isLogin: '_IsLogin', // 是否登录
        userStatus: '_UserStatus', // 获取用户状态
        login: '_AppLogin', // 登录
        getAppToken: '_GetAppToken', // 获取app token
        authenticate: '_Authenticate', // 用户去认证
      }
    },
    network: {
      module: 'jssdkCallNetwork',
      methods: {
        nettype: '_NetStatus', // 获取网络状态
      }
    },
    image: {
      module: 'jssdkCallImage',
      methods: {
        selectimage: '_SelectImage',  // 选择图片
      }
    },
    route: {
      module: 'jssdkCallRoute',
      methods: {
        gotoPage: '_GotoPage', // 跳转页面
        openapp: '_OpenAPP', // 打开app
        canopenapp: '_CanOpenAPP', // 是否可以打开app
      }
    },
    scan: {
      module: 'jssdkCallScan',
      methods: {
        qrcode: '_QRCode', // 扫描二维码
        OCR: '_OCR', // OCR识别
      }
    },
    file: {
      module: 'jssdkCallFile',
      methods: {
        previewfile: '_PreviewFile', // 预览文件
      }
    },
    appData: {
      module: 'jssdkCallAppData',
      methods: {
        appInfo: '_AppInfo', // 获取app信息
        chooseCredentials: '_ChooseCredentials', // 选择证件
      }
    },
    share: {
      module: 'jssdkCallShare',
      methods: {
        shareurl: '_ShareUrl', // 分享链接
        shareimage: '_ShareImage',  // 分享图片
        openminiprogram: '_OpenMiniProgram' // 打开小程序
      }
    },
    pay: {
      module: 'jssdkCallPay',
      methods: {
        alipay: '_ALiPay', // 支付宝支付
        wxpay: '_WXPay', // 微信支付
      }
    },
    navigation: {
      module: 'jssdkCallNavigation',
      methods: {
        hideMorePannel: '_HideMorePannel', // 隐藏更多面板
        configMorePannel: '_ConfigMorePannel', // 配置更多面板(没数量限制)
        closeWebview: '_CloseWebview', // 关闭当前页面
      }
    }
  }

  var _pjo = { modelinfo: modelinfo }

  // 创建模块函数并添加到_pjo对象中
  for (var moduleName in modules) {
    var module = modules[moduleName]
    _pjo[moduleName] = {}
    for (var methodName in module.methods) {
      _pjo[methodName] = createModuleFunction(module.module, module.methods[methodName])
    }
  }
  return _pjo
})()
